﻿using System;
using System.Text;
using AutoMapper;
using Coder;
using Fee;
using Fee.Extentions;
using Fee.FileAttachs;
using Fee.ViewModel;
using Identity;
using Identity.ViewModels;
using JwtWebApi.Data;
using JwtWebApi.Filters;
using JwtWebApi.Models;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using Pomelo.EntityFrameworkCore.MySql.Infrastructure;
//using Pomelo.EntityFrameworkCore.MySql.Infrastructure;
using Swashbuckle.AspNetCore.Swagger;

namespace JwtWebApi
{
    public class Startup
    {
        private readonly IHostingEnvironment _environment;

        public Startup(IConfiguration configuration, IHostingEnvironment environment)
        {
            _environment = environment;
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(builder => builder.AddDefaultPolicy(
                    opt =>
                        opt.AllowAnyOrigin()
                            .AllowAnyMethod()
                            .AllowAnyHeader()
                            .AllowCredentials()
                )
            );

            services.AddMvc(mvcOptions =>
                {
                    mvcOptions.Filters.Add<CustomExceptionFilterAttribute>();
                    mvcOptions.Filters.Add<PermissionFilter>();
                }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                .AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);

            //AddIdentity 必须 再 AddAuthentication 之前，否则 AddAuthentication 的设置就 不生效。
            services.AddIdentity<User, Role>(option =>
                {
                    option.SignIn.RequireConfirmedEmail = false;
                    option.SignIn.RequireConfirmedPhoneNumber = false;
                })
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();


            //swgger api 文档自动生成。
            services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Title = "WellDell API", Version = "v1" }); });

            // configure strongly typed settings objects
            var appSettingsSection = Configuration.GetSection("AppSettings");
            services.Configure<AppSettings>(appSettingsSection);

            // configure jwt authentication
            var appSettings = appSettingsSection.Get<AppSettings>();
            var key = Encoding.UTF8.GetBytes(appSettings.Secret);
            services.AddAuthentication(x =>
                {
                    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                .AddJwtBearer(x =>
                {
                    x.RequireHttpsMetadata = false;
                    x.SaveToken = true;
                    x.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKey = new SymmetricSecurityKey(key),
                        ValidateIssuer = false,

                        ValidateAudience = false
                    };
                });
            var dbType = Configuration["databaeType"];
            if (dbType == "mssql")
                services.AddDbContext<ApplicationDbContext>(options =>
                    {
                        options.UseSqlServer(Configuration.GetConnectionString("mssql"),
                            f => f.UseRowNumberForPaging(true)
                        );
                    }
                );
            else if (dbType == "mysql")
            {

                services.AddDbContextPool<ApplicationDbContext>(
                    options1 => options1.UseMySql(Configuration.GetConnectionString("mysql"),
                        mySqlOptions => { mySqlOptions.ServerVersion(new Version(5, 7, 19), ServerType.MySql); }
                    ));
            }

            //Fee 相关
            var xinJuConnection = this.Configuration.GetConnectionString("xinJu");
            services.AddFeeServices<ApplicationDbContext>(xinJuConnection);
            services.AddWorkflow<ApplicationDbContext>();
            //文件管理器注册

            services.AddScoped<FileManager>(sp =>
            {
                var folder = _environment.ContentRootPath;
                return new FileManager(folder);
            });
            //autoMapper
            Mapper.Initialize(cfg =>
            {
                cfg.CreateMap<Project, ProjectDetailViewModel>();
                cfg.CreateMap<Vendor, VendorDetailViewModel>();
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            //注意顺序

            if (env.IsDevelopment())
                app.UseDeveloperExceptionPage();
            else
                app.UseHsts();


            app.UseAuthentication();

            //  app.UseHttpsRedirection(); 强制 https
            app.UseMvc();

            app.UseCors();
            app.UseSwagger(); //必须再usemvc之后
            app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "WellDell V1"); });
        }
    }
}